package cn.tedu.csmall.product.filter;


import cn.tedu.csmall.product.security.LoginPrincipal;
import cn.tedu.csmall.product.web.JsonResult;
import cn.tedu.csmall.product.web.ServiceCode;
import com.alibaba.fastjson.JSON;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;

/**
 * @author 程旭东
 */
@Slf4j
@Component
public class JwtAuthorizationFilter extends OncePerRequestFilter {

    private static final int JWT_MIN_LENGTH = 100;

    @Value("${csmall.jwt.securityKey}")
    private String secretKey;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        //清除SecurityContextHolder中原有的数据
        SecurityContextHolder.clearContext();

        //尝试获取客户端传入的JWT数据
        String jwt = request.getHeader("Authorization");
        log.debug("接收到JWT数据：{}", jwt);
        // 放行

        //判断是否获取到有效的JWT
        if(!StringUtils.hasText(jwt) || jwt.length()<JWT_MIN_LENGTH){
            log.debug("未获取到有效数据，直接放行");
            filterChain.doFilter(request, response);
            return ;
        }

        //尝试解析JWT，从中获取用户的相关数据
        log.debug("尝试解析用户数据");
        Claims claims = null;

        try{
            claims = Jwts.parser().setSigningKey(secretKey).parseClaimsJws(jwt).getBody();
        }catch (SignatureException e){
            String message = "登录已过期，请重新登录";
            JsonResult jsonResult = JsonResult.fail(ServiceCode.ERR_JWT_SIGNATURE, message);
            String toJSONString = JSON.toJSONString(jsonResult);
            PrintWriter writer = response.getWriter();
            writer.println(toJSONString);
            writer.close();
            return ;
        }
        catch (Throwable e){
            String message = "服务器忙，请稍后重试";
            JsonResult jsonResult = JsonResult.fail(ServiceCode.ERR_SYSTEM_ERROR, message);
            String toJSONString = JSON.toJSONString(jsonResult);
            PrintWriter writer = response.getWriter();
            writer.println(toJSONString);
            writer.close();
            return ;
        }

        String username = claims.get("username", String.class);
        String authorities = claims.get("authorities",String.class);
        log.info("接收到的username为：{}",username);
        log.info("接收到的authorities为：{}",authorities);

        //根据从JWT中获取到的数据来创建验证信息
        List<SimpleGrantedAuthority> grantedAuthorities = JSON.parseArray(authorities, SimpleGrantedAuthority.class);




        LoginPrincipal loginPrincipal = new LoginPrincipal();
        loginPrincipal.setUsername(username);

        Authentication authentication = new UsernamePasswordAuthenticationToken(
                loginPrincipal,null,grantedAuthorities
        );

        //将数据存储到SecurityContext中
        SecurityContext securityContext = SecurityContextHolder.getContext();
        securityContext.setAuthentication(authentication);

        filterChain.doFilter(request, response);

    }
}
